package top.linyuxb.lycloud.admin.service.impl;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import jakarta.annotation.Resource;
import jakarta.persistence.criteria.Predicate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import top.linyuxb.lycloud.admin.constant.StatusEnum;
import top.linyuxb.lycloud.admin.entity.*;
import top.linyuxb.lycloud.admin.repository.LyConfEnvRepository;
import top.linyuxb.lycloud.admin.repository.LyConfNodeRepository;
import top.linyuxb.lycloud.admin.repository.LyConfProjectRepository;
import top.linyuxb.lycloud.admin.repository.LyConfServerRepository;
import top.linyuxb.lycloud.admin.service.ILyConfNodeService;
import top.linyuxb.lycloud.admin.service.ILyConfPermissionService;
import top.linyuxb.lycloud.admin.utils.EntityUtil;
import top.linyuxb.lycloud.admin.utils.ReturnT;

import java.util.*;

/**
 * Created by Intellij IDEA.
 *
 * @Author: linyuxb
 * @Date: 2024/7/29 14:43
 * @Desc: 配置服务
 */
@Slf4j
@Service(value = "lyConfNodeService")
public class LyConfNodeServiceImpl implements ILyConfNodeService {
    @Resource
    private LyConfNodeRepository lyConfNodeRepository;
    @Resource
    private LyConfProjectRepository lyConfProjectRepository;
    @Resource
    private LyConfEnvRepository lyConfEnvRepository;
    @Resource
    private LyConfServerRepository lyConfServerRepository;
    @Resource
    private ILyConfPermissionService lyConfPermissionService;

    @Override
    public Map<String, Object> pageList(int offset, int pagesize, String app, String key,
                                        LyCloudUserEntity loginUser, String loginEnv) {
        // project permission
        if (StringUtils.isBlank(loginEnv) || StringUtils.isBlank(app) ||
                !lyConfPermissionService.ifHasProjectPermission(loginUser, loginEnv, app)) {
            Map<String, Object> emptyMap = new HashMap<>();
            emptyMap.put("data", new ArrayList<>());
            emptyMap.put("recordsTotal", 0);
            emptyMap.put("recordsFiltered", 0);
            return emptyMap;
        }

        Page<LyConfNodeEntity> all = lyConfNodeRepository.findAll(
                (root, criteriaQuery, cb) -> {
                    List<Predicate> predicates = new ArrayList<>();
                    if (StringUtils.isNotBlank(loginEnv)) {
                        predicates.add(cb.equal(root.get("env").as(String.class), loginEnv));
                    }
                    if (StringUtils.isNotBlank(app)) {
                        predicates.add(cb.equal(root.get("app").as(String.class), app));
                    }
                    if (StringUtils.isNotBlank(key)) {
                        predicates.add(cb.like(root.get("key").as(String.class), "%" + key + "%"));
                    }
                    predicates.add(cb.equal(root.get("status").as(Integer.class), StatusEnum.VALID.getType()));
                    return cb.and(predicates.toArray(new Predicate[0]));
                },
                PageRequest.of(
                        (offset > 0 ? offset / pagesize : 0), pagesize,
                        Sort.by(Sort.Direction.DESC, "id"))
        );
        List<LyConfNodeEntity> data = all.getContent();
        int list_count = (int) all.getTotalElements();

        // package result
        Map<String, Object> maps = new HashMap<>();
        maps.put("data", data);
        maps.put("recordsTotal", list_count);        // 总记录数
        maps.put("recordsFiltered", list_count);    // 过滤后的总记录数
        return maps;

    }

    @Override
    public ReturnT<String> delete(Long id, LyCloudUserEntity loginUser, String loginEnv) {
        if (Objects.isNull(id)) {
            return new ReturnT<>(500, "参数缺失");
        }
        LyConfNodeEntity existNode = lyConfNodeRepository.findByIdAndStatus(id, StatusEnum.VALID.getType());
        if (Objects.isNull(existNode)) {
            return new ReturnT<>(500, "参数非法");
        }

        // project permission
        if (!lyConfPermissionService.ifHasProjectPermission(loginUser, loginEnv, existNode.getApp())) {
            return new ReturnT<>(500, "您没有该项目的配置权限,请联系管理员开通");
        }
        lyConfNodeRepository.removeById(existNode.getId());

        return ReturnT.SUCCESS;
    }

    @Override
    public ReturnT<String> add(LyConfNodeEntity lyConfNode, LyCloudUserEntity loginUser, String loginEnv) {
        // valid
        if (StringUtils.isBlank(lyConfNode.getApp())) {
            return new ReturnT<>(500, "AppName不可为空");
        }
        // project permission
        if (!lyConfPermissionService.ifHasProjectPermission(loginUser, loginEnv, lyConfNode.getApp())) {
            return new ReturnT<>(500, "您没有该项目的配置权限,请联系管理员开通");
        }
        // valid group
        LyConfProjectEntity group = lyConfProjectRepository.findByApp(lyConfNode.getApp());
        if (group == null) {
            return new ReturnT<>(500, "AppName非法");
        }
        // valid env
        if (StringUtils.isBlank(lyConfNode.getEnv())) {
            return new ReturnT<>(500, "配置Env不可为空");
        }
        LyConfEnvEntity lyConfEnv = lyConfEnvRepository.findByEnv(lyConfNode.getEnv());
        if (lyConfEnv == null) {
            return new ReturnT<>(500, "配置Env非法");
        }
        // valid key
        if (StringUtils.isBlank(lyConfNode.getKey())) {
            return new ReturnT<>(500, "配置Key不可为空");
        }
        lyConfNode.setKey(lyConfNode.getKey().trim());
        // valid title
        if (StringUtils.isBlank(lyConfNode.getTitle())) {
            return new ReturnT<>(500, "配置描述不可为空");
        }
        // value force null to ""
        if (Objects.isNull(lyConfNode.getValue())) {
            lyConfNode.setValue("");
        }
        // add node
        lyConfNodeRepository.save(lyConfNode);
        return ReturnT.SUCCESS;
    }

    @Override
    public ReturnT<String> update(LyConfNodeEntity lyConfNode, LyCloudUserEntity loginUser, String loginEnv) {
        // valid
        if (StringUtils.isBlank(lyConfNode.getKey())) {
            return new ReturnT<>(500, "配置Key不可为空");
        }
        LyConfNodeEntity existNode = lyConfNodeRepository.findByIdAndStatus(lyConfNode.getId(), StatusEnum.VALID.getType());
        if (Objects.isNull(existNode)) {
            return new ReturnT<>(500, "配置主键非法");
        }
        // project permission
        if (!lyConfPermissionService.ifHasProjectPermission(loginUser, loginEnv, existNode.getApp())) {
            return new ReturnT<>(500, "您没有该项目的配置权限,请联系管理员开通");
        }
        if (StringUtils.isBlank(lyConfNode.getTitle())) {
            return new ReturnT<>(500, "配置描述不可为空");
        }
        // value force null to ""
        if (Objects.isNull(lyConfNode.getValue())) {
            lyConfNode.setValue("");
        }
        BeanUtils.copyProperties(lyConfNode, existNode, EntityUtil.getNullPropertyNames(lyConfNode));
        lyConfNodeRepository.save(existNode);
        return ReturnT.SUCCESS;
    }

    @Override
    public void refreshConf(String env, String app) {
        List<LyConfServerEntity> byStatusOrderByIdDesc = lyConfServerRepository.findByEnvAndAppOrderByIdDesc(env, app);
        for (LyConfServerEntity lyConfServerEntity : byStatusOrderByIdDesc) {
            String url = "http://" + lyConfServerEntity.getServerIp() + ":" + lyConfServerEntity.getServerPort() + "/lyConf/refreshConf";
            Map<String, String> headers = new HashMap<>();
            headers.put("user", lyConfServerEntity.getUser());
            headers.put("password", lyConfServerEntity.getUserPassword());
            try (HttpResponse response = HttpRequest.post(url)
                         .addHeaders(headers)
                         .timeout(1000)
                         .execute()){
            } catch (Exception e) {
                log.error("lyConfNodeService refreshConf error", e);
            }
        }
    }
}
